// 写请求
#include <stdio.h>
#include <sys/time.h>
#include <sched.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <error.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>          // 系统调用相关的函数 close()
#include <string.h>          // strcpy, memset(), and memcpy()
#include <sys/types.h>       // 包含了一些基本的系统数据类型 uint8_t、uint16_t 和 uint32_t
#include <sys/socket.h>      // 与套接字相关的函数和数据结构
#include <netinet/in.h>      // 与 Internet 协议族相关的数据结构
#include <netinet/ip.h>      // IP 协议头部的数据结构
#include <netinet/ip_icmp.h> // 定义了 ICMP 协议头部的数据结构
#include <arpa/inet.h>       // 定义了一些 IP 地址转换函数
#include <sys/ioctl.h>       // 进行输入/输出控制的函数和相关宏
#include <bits/ioctls.h>     // 用于 ioctl() 函数的参数
#include <net/if.h>          // 处理网络接口相关的函数和数据结构
#include <linux/if_ether.h>  // 帧格式 以太网帧的一些常量
#include <linux/if_packet.h> // 用于与套接字相关联的网络接口的数据结构 struct sockaddr_ll
#include <net/ethernet.h>    // 以太网帧的数据结构
#include <errno.h>           // errno, perror()
#include <vector>
#include "tsmp.h"
#include "ptp.h"

#define ETH_P_DEAN 0xff01 // 自定义的以太网协议 type
#define PACKET_LEN 2048    // 数据包的最大长度为 2048 字节
#define NET_INIT "enp12s0"



struct sockaddr_ll device;
struct ifreq ifr;
int frame_length, sd, bytes;
uint8_t tsmp_frame[IP_MAXPACKET];
struct Tsmp_head_send frame_head; // 构造TSMP发送报文头

// 找到网卡名对应的MAC地址
int itf_mac(const char *interface)
{
    int i, sd;
    uint8_t src_mac[6];

    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
    { // 第一次创建socket是为了获取本地网卡信息
        perror("socket() failed to get socket descriptor for using ioctl() ");
        exit(EXIT_FAILURE);
    }

    // Use ioctl() to look up interface name and get its MAC address.
    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
    if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    {
        perror("ioctl() failed to get source MAC address ");
        return (EXIT_FAILURE);
    }
    close(sd);

    // Copy source MAC address.
    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6);

    // Report source MAC address to stdout.
    printf("MAC address for interface %s is ", interface);
    for (i = 0; i <= 5; i++)
    {
        printf("%02x:", src_mac[i]);
    }

    // Find interface index from interface name and store index in
    // struct sockaddr_ll device, which will be used as an argument of sendto().
    memset(&device, 0, sizeof(device));
    if ((device.sll_ifindex = if_nametoindex(interface)) == 0)
    {
        perror("if_nametoindex() failed to obtain interface index ");
        exit(EXIT_FAILURE);
    }
    printf("\nIndex for interface %s is %i\n", interface, device.sll_ifindex);

    // Fill out sockaddr_ll.
    device.sll_family = AF_PACKET;
    device.sll_halen = htons(6);
    return 0;
}

int socket_send(uint8_t tsmp_frame[], int frame_length)
{
    // Submit request for a raw socket descriptor.
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
    { // 创建正真发送的socket
        perror("socket() failed ");
        exit(EXIT_FAILURE);
    }

    if ((bytes = sendto(sd, tsmp_frame, frame_length, 0, (struct sockaddr *)&device, sizeof(device))) <= 0)
    {
        perror("sendto() failed");
        exit(EXIT_FAILURE);
    }
    printf("send num=%d\n", bytes);
    printf("\n");
    // Close socket descriptor.
    close(sd);
    return 0;
}

int writeReqSend(uint32_t addr, int data_n, uint32_t data[])
{
    memset(tsmp_frame, 0, sizeof(tsmp_frame));
    struct W_req_send frame_payload; // 构造TSMP写请求发送帧
    int result = itf_mac(NET_INIT);
    if (result != 0)
    {
        printf("can not find mac.\n");
        return -1;
    }
    // 写TSMP帧头
    frame_head.version = 0x01; // 固定为0x01，表示是第1版TSMP协议
    frame_head.type = 0x01;    //        0x01：写请求
    frame_head.reserve = 0x66; //     保留
    frame_head.control = 0x00; //  0x00：不需发送响应

    frame_head.out_intface = htonl(0x01021234); // 32个输出接口的bitmap，因此TSMP发送操作支持组播。
    frame_head.head_reserve = htonl(0x56789012);

    frame_head.ptcl_id = htons(0xff01);
    frame_head.frame_id = htons(0xffff);

    // 将TSMP头弄到发送帧中
    memcpy(tsmp_frame, &frame_head, sizeof(frame_head));

    // 写TSMP负载
    frame_payload.data_n = htons(data_n);     // 写入1个数据
    frame_payload.reserve = htons(0x00); // 保留字段填0
    frame_payload.addr = htonl(addr);    // 写 地址
    // char data[datalen] = data;
    int totalSize = data_n * sizeof(data[0]);
    memcpy(&frame_payload.data, data, totalSize);

    // data
    memcpy(tsmp_frame + sizeof(frame_head), &frame_payload, sizeof(frame_payload));

    // Fill out ethernet frame header.
    frame_length = sizeof(frame_head) + 8 + totalSize;

    return socket_send(tsmp_frame, frame_length);
}

int readReqSend(uint32_t addr, uint16_t N)
{
    memset(tsmp_frame, 0, sizeof(tsmp_frame));
    int result = itf_mac(NET_INIT);
    if (result != 0)
    {
        printf("can not find mac.\n");
        return -1;
    }
    struct R_req_send frame_payload; // 构造TSMP写请求发送帧
    // 读请求TSMP帧头
    frame_head.version = 0x01; // 固定为0x01，表示是第1版TSMP协议
    frame_head.type = 0x00;    //        0x00：读请求
    frame_head.reserve = 0x66; //     保留
    frame_head.control = 0x01; //  0x01：需发送响应

    frame_head.out_intface = htonl(0x01021234); // 32个输出接口的bitmap，因此TSMP发送操作支持组播。
    frame_head.head_reserve = htonl(0x56789012);

    frame_head.ptcl_id = htons(0xff01);
    frame_head.frame_id = htons(0xffff);

    // 将TSMP头弄到发送帧中
    memcpy(tsmp_frame, &frame_head, sizeof(frame_head));

    // 写TSMP负载
    frame_payload.data_n = htons(N);     // 读N个数据
    frame_payload.reserve = htons(0x00); // 保留字段填0
    frame_payload.addr = htonl(addr);    // 读 地址

    // 组装
    memcpy(tsmp_frame + sizeof(frame_head), &frame_payload, sizeof(frame_payload));

    // Fill out ethernet frame header.
    frame_length = sizeof(frame_head) + sizeof(frame_payload);
    return socket_send(tsmp_frame, frame_length);
}

int packSend(uint8_t *pack_ptp, uint8_t control)
{
    memset(tsmp_frame, 0, sizeof(tsmp_frame));
    int result = itf_mac(NET_INIT);
    if (result != 0)
    {
        printf("can not find mac.\n");
        return -1;
    }
    struct Pack_send frame_payload; // 构造TSMP封装发送负载
    // 读请求TSMP帧头
    frame_head.version = 0x01; // 固定为0x01，表示是第1版TSMP协议
    frame_head.type = 0x02;    //        0x02：封装帧
    frame_head.reserve = 0x66; //     保留
    frame_head.control = control; //  0x01：需发送响应

    frame_head.out_intface = htonl(0x01021234); // 32个输出接口的bitmap，因此TSMP发送操作支持组播。
    frame_head.head_reserve = htonl(0x56789012);

    frame_head.ptcl_id = htons(0xff01);
    frame_head.frame_id = htons(0xffff);

    // 将TSMP头弄到发送帧中
    memcpy(tsmp_frame, &frame_head, sizeof(frame_head));

    // 写TSMP负载
    PtpHeader *pp = (PtpHeader *)pack_ptp;
    int size = pp->message_length; // 获取PTP头部的消息长度
    // printf("log_message_interval:%d\n",pp->log_message_interval);    //验证PTP消息传递正确
    std::vector<uint8_t> vec(10, 0);                // 创建一个包含10个uint8_t的vector，所有元素初始化为0
    frame_payload.pack_ptp = vec.data();            // 初始化frame_payload.pack_ptp指针
    memcpy(frame_payload.pack_ptp, pack_ptp, size); // 赋值size长度的PTP消息给TSMP负载

    // 组装
    memcpy(tsmp_frame + sizeof(frame_head), frame_payload.pack_ptp, size);

    // Fill out ethernet frame header.
    frame_length = size + sizeof(frame_head);
    return socket_send(tsmp_frame, frame_length);
}